require "rubygems"
require "logger"
require "ruby-debug"
Debugger.start

require "gene"
require "chromloc"

$: << Dir.pwd + "/lib/con_code/plugins"
# Plugins
require "plugin"
require "plugin_probe_summary"
require "plugin_group_summary"

$NA = "NA"

class FileCondense

	GROUPED_PROBE_OUT = [:Probe_Name, :Probe_Value, :Chrom_Loc]
	attr_reader :data, :file, :plugin_obj

	def initialize( file_name, key = "SystematicName" )
		Gene.reset

		@Key = key

		@file = File.open(file_name)
		map_header( get_line )

		@data = {}

		# The classes for the plugins which will be ran after flattening
		@plugins = [ProbeSummary, GroupSummary]
		@probe_output = [[:Probe_Name, ';'], [:Chrom_Loc, ";"], [:Probe_Value, "\t"]]
	end

	def set_probe_output( output_format )
		@probe_output = output_format
	end


	def get_line
		@file.readline
	end

	def get_split
		split_line get_line
	end

	def rewind
		@file.rewind
		get_line
	end

	def parse_all
		@file.rewind
		get_line
		puts "Parsing lines..."
		parse_line while !@file.eof?
		puts "Done parsing the data, running any plugins."
		run_plugins
	end

	def parse_line( l = nil ) 
		dat = get_split if( !l )
		temp_key = one_data( @Key, dat )

		if( !@data.has_key?( temp_key ) )
			new_gene = Gene.new( temp_key, [], @probe_output )

			g_name = one_data( "GeneName", dat )
			g_descript = one_data( "Description", dat )
			new_gene.add_attribute("GeneName", "\"#{g_name}\"" )
			new_gene.add_attribute("Description","\"#{g_descript}\"")
			new_gene.add_attribute("ProbeAvg", "probe_avg" )
			@data[temp_key] = new_gene
		end	

		probe_key = one_data("ProbeName", dat)
		@data[temp_key].add_probe_data( probe_key, one_data("LogRatio", dat) )
	end

	def group_probes_by_loc
		@data.values.each {|v| v.group_probes}
	end

	# Run all of the plutins on the parsed data.
	def run_plugins
		# Initialize the plugins
		@plugin_obj = @plugins.map { |p| p.new }

		# Pass all of the data to the plugins
		@data.values.each do |g|
			@plugin_obj.each { |p| p.push_gene(g) }
		end

		# Finalize
		@plugin_obj.each do |p|
			p.finalize
			puts p.to_s
			puts "\n"
		end

	end

	# Take the header and create an array from it
	def map_header( header )
		@unit_header = header.strip.split( "\t\t\t" )[0].split("\t")
	end

	def all_data( header_name, line )
		line.map {|dat| dat[@unit_header.index( header_name )] }
	end

	def one_data( header_name, line, segment = 0 )
		line[segment][@unit_header.index( header_name )] 
	end


	def split_line( line )
		line.strip.split( "\t\t\t" ).map{ |elt| elt.split( "\t" )}
	end

	def to_s
		"Condenser"
	end

	def to_file( f_name )
		f = File.open(f_name, 'w')
		
		puts "Writing to " + f_name + "..."
		# Write the header, getting it from a (fairly) random gene
		f.write( @data.values[0].header + "\n" )
		@data.sort.each { |v| f.write( v[1].to_s + "\n" ) }
		f.close
		puts "File Written"
	end

	def write_grouped_probes( f_name, output_attribs = GROUPED_PROBE_OUT )
		f_out = File.open( f_name, 'w')

		head_s = "GeneName\t\t" + output_attribs.join("\t" * (Gene.group_count + 1))
		f_out.write(head_s + "\n")

		@data.sort.each do |v|
			if(v[1].probe_groups)
				f_out.write( v[0] + "\t\t" + 
								v[1].probe_groups.group_to_s(GROUPED_PROBE_OUT) )
			end
		end

		f_out.close
	end

end

def run
	@temp = FileCondense.new( "reworked.txt" )
	@temp.parse_all
end


=begin
ARGV.each do |arg|
	fc = FileCondense.new arg
	fc.parse_all
	fc.to_file("parsed_" + arg)
end
=end
